package scheduler

import (
	"fmt"
	"log"
	"sync"
	"time"

	"github.com/google/uuid"
	"github.com/robfig/cron/v3"
	"skedule-backend/storage"
	"skedule-backend/types"
)

// TaskExecutor 定义任务执行器接口
type TaskExecutor interface {
	ExecuteTask(taskID string) (*types.ExecuteTaskResponse, error)
}

// Scheduler 调度器
type Scheduler struct {
	cron         *cron.Cron
	tasks        map[string]cron.EntryID
	taskStore    *storage.TaskStore
	logStore     *storage.LogStore
	taskExecutor TaskExecutor // 任务执行器
	lock         sync.RWMutex
}

// New 创建新的调度器
func New(taskStore *storage.TaskStore, logStore *storage.LogStore, taskExecutor TaskExecutor) *Scheduler {
	return &Scheduler{
		cron:         cron.New(cron.WithSeconds()),
		tasks:        make(map[string]cron.EntryID),
		taskStore:    taskStore,
		logStore:     logStore,
		taskExecutor: taskExecutor,
	}
}

// Start 启动调度器
func (s *Scheduler) Start() error {
	s.lock.Lock()
	defer s.lock.Unlock()

	// 加载所有任务
	tasks := s.taskStore.GetAllTasks()
	for _, task := range tasks {
		if task.Enabled {
			if err := s.scheduleTask(task); err != nil {
				log.Printf("Failed to load task [%s]: %v", task.ID, err)
			}
		}
	}

	s.cron.Start()
	return nil
}

// Stop 停止调度器
func (s *Scheduler) Stop() {
	s.lock.Lock()
	defer s.lock.Unlock()

	if s.cron != nil {
		s.cron.Stop()
	}
}

// AddTask 添加任务
func (s *Scheduler) AddTask(task *storage.Task) error {
	s.lock.Lock()
	defer s.lock.Unlock()

	// 如果ID为空，生成任务ID
	if task.ID == "" {
		task.ID = uuid.New().String()
	}

	// 保存任务
	if err := s.taskStore.CreateTask(task); err != nil {
		return fmt.Errorf("failed to save task: %v", err)
	}

	// 如果任务启用，则调度它
	if task.Enabled {
		if err := s.scheduleTask(task); err != nil {
			return fmt.Errorf("failed to schedule task: %v", err)
		}
	}

	return nil
}

// ScheduleTask 仅调度任务（不保存到数据库）
func (s *Scheduler) ScheduleTask(task *storage.Task) error {
	s.lock.Lock()
	defer s.lock.Unlock()

	// 如果任务启用，则调度它
	if task.Enabled {
		if err := s.scheduleTask(task); err != nil {
			return fmt.Errorf("failed to schedule task: %v", err)
		}
	}

	return nil
}

// UpdateTask 更新任务
func (s *Scheduler) UpdateTask(task *storage.Task) error {
	s.lock.Lock()
	defer s.lock.Unlock()

	// 如果任务已经在运行，先移除它
	if entryID, exists := s.tasks[task.ID]; exists {
		s.cron.Remove(entryID)
		delete(s.tasks, task.ID)
	}

	// 更新任务
	if err := s.taskStore.UpdateTask(task); err != nil {
		return fmt.Errorf("failed to update task: %v", err)
	}

	// 如果任务启用，重新调度
	if task.Enabled {
		if err := s.scheduleTask(task); err != nil {
			return fmt.Errorf("failed to reschedule task: %v", err)
		}
	}

	return nil
}

// DeleteTask 删除任务
func (s *Scheduler) DeleteTask(id string) error {
	s.lock.Lock()
	defer s.lock.Unlock()

	// 如果任务在运行，先停止它
	if entryID, exists := s.tasks[id]; exists {
		s.cron.Remove(entryID)
		delete(s.tasks, id)
	}

	// 从存储中删除任务
	return s.taskStore.DeleteTask(id)
}

// EnableTask 启用任务
func (s *Scheduler) EnableTask(id string) error {
	s.lock.Lock()
	defer s.lock.Unlock()

	// 获取任务
	task, err := s.taskStore.GetTask(id)
	if err != nil {
		return fmt.Errorf("failed to get task: %v", err)
	}

	// 更新状态
	task.Enabled = true
	
	// 计算下次运行时间
	nextRun := s.getNextRunTime(task.Schedule)
	if !nextRun.IsZero() {
		task.NextRun = nextRun
	}
	
	if err := s.taskStore.UpdateTask(task); err != nil {
		return fmt.Errorf("failed to update task status: %v", err)
	}

	// 调度任务
	return s.scheduleTask(task)
}

// DisableTask 禁用任务
func (s *Scheduler) DisableTask(id string) error {
	s.lock.Lock()
	defer s.lock.Unlock()

	// 如果任务在运行，停止它
	if entryID, exists := s.tasks[id]; exists {
		s.cron.Remove(entryID)
		delete(s.tasks, id)
	}

	// 获取任务
	task, err := s.taskStore.GetTask(id)
	if err != nil {
		return fmt.Errorf("failed to get task: %v", err)
	}

	// 更新状态
	task.Enabled = false
	task.NextRun = time.Time{} // 清空下次运行时间
	if err := s.taskStore.UpdateTask(task); err != nil {
		return fmt.Errorf("failed to update task status: %v", err)
	}

	return nil
}

// scheduleTask 调度任务
func (s *Scheduler) scheduleTask(task *storage.Task) error {
	entryID, err := s.cron.AddFunc(task.Schedule, func() {
		log.Printf("Scheduler auto-executing task: %s [%s]", task.Name, task.ID)
		
		// 使用TaskExecutionService执行任务，复用完整的执行逻辑
		if s.taskExecutor != nil {
			if resp, err := s.taskExecutor.ExecuteTask(task.ID); err != nil {
				log.Printf("Scheduler failed to execute task [%s]: %v", task.ID, err)
			} else if !resp.Success {
				log.Printf("Scheduler failed to execute task [%s]: %s", task.ID, resp.Message)
			} else {
				log.Printf("Scheduler executed task successfully [%s]: %s", task.ID, resp.ExecutionID)
			}
		} else {
			log.Printf("Scheduler failed to execute task [%s]: TaskExecutor not set", task.ID)
		}

		// 更新任务运行时间
		task.LastRun = time.Now()
		task.NextRun = s.getNextRunTime(task.Schedule)
		if err := s.taskStore.UpdateTaskRunTime(task.ID, task.LastRun, task.NextRun); err != nil {
			log.Printf("Failed to update task runtime [%s]: %v", task.ID, err)
		}
	})

	if err != nil {
		return fmt.Errorf("failed to add cron job: %v", err)
	}

	s.tasks[task.ID] = entryID
	
	// 调度成功后立即计算并更新nextRun（如果还没有设置）
	if task.NextRun.IsZero() {
		nextRun := s.getNextRunTime(task.Schedule)
		if !nextRun.IsZero() {
			task.NextRun = nextRun
			if err := s.taskStore.UpdateTaskRunTime(task.ID, task.LastRun, nextRun); err != nil {
				log.Printf("Failed to update NextRun when scheduling task [%s]: %v", task.ID, err)
			}
		}
	}
	
	return nil
}

// getNextRunTime 获取下次运行时间
func (s *Scheduler) getNextRunTime(schedule string) time.Time {
	parser := cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
	schedule = schedule
	if sched, err := parser.Parse(schedule); err == nil {
		return sched.Next(time.Now())
	}
	return time.Time{}
}

// GetTaskStatus 获取任务状态
func (s *Scheduler) GetTaskStatus(id string) (bool, error) {
	s.lock.RLock()
	defer s.lock.RUnlock()

	_, exists := s.tasks[id]
	return exists, nil
}

// RemoveTask 移除任务（从调度器中移除，但不删除数据）
func (s *Scheduler) RemoveTask(id string) {
	s.lock.Lock()
	defer s.lock.Unlock()

	if entryID, exists := s.tasks[id]; exists {
		s.cron.Remove(entryID)
		delete(s.tasks, id)
	}
}

// GetRunningTasks 获取正在运行的任务数量
func (s *Scheduler) GetRunningTasks() int {
	s.lock.RLock()
	defer s.lock.RUnlock()

	return len(s.tasks)
} 